package models;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;

import org.apache.commons.mail.EmailException;

import controllers.Topics;

import play.data.validation.*;
import play.db.jpa.Model;

import java.util.*;
import javax.persistence.*;


@Entity
public class Tag extends Model {
	
	@Required
	private String name = "";
	@OneToMany (mappedBy = "relatedTag", cascade=CascadeType.ALL)
	public List<Role> roles;
	@Required
	@ManyToMany
	private List<User> users;
	@Required
	private String status;
	// @Required
	// private String description; // Author nora don't see why we are going to
	// need a description if needed send me an e-mail
	@Required
	@ManyToMany
	private List<Organization> taggedOrganizations;
	@Required
	@ManyToMany
	private List<Idea> taggedIdeas;
	@Required
	@ManyToMany
	private List<Eentity> taggedEntity;
//	@Required
//	private List<String> tagNames; // author nora added@2011/4/28
	@Required
	@ManyToMany
	private List<Topic> taggedTopics; // author nora added@2011/4/28
	@ManyToMany (mappedBy = "tags",  cascade=CascadeType.ALL)
	private List<Item> items;
	@Required
	private Role role;
	/**
	 * the default constructor for a tag
	 *
	 * @author     nora zakhary
	 * @version    2011.04.29
	 *  
	 */
	public Tag() {

		
	
		
		users = new LinkedList<User>();
		this.status = "";
		this.taggedOrganizations = new LinkedList<Organization>();
		this.taggedIdeas = new LinkedList<Idea>();
		this.taggedEntity = new LinkedList<Eentity>();
//		this.tagNames = new LinkedList<String>();
		this.taggedTopics = new LinkedList<Topic>();
		this.items = new LinkedList<Item> ();
	}

	/**
	 * constructor for a tagging an idea
	 *
	 * @author     nora zakhary
	 * @version    2011.04.29
	 * @param      User owner, String name, int creatorId,
			LinkedList<User> followers, String status,
			LinkedList<Idea> taggedIdeas, Idea newlyTaggedIdea,
			LinkedList<String> tagNames    
	 */

	public Tag(User owner, String name,
			 String status,
			LinkedList<Idea> taggedIdeas
		/*LinkedList<String> tagNames*/) {
		this();
		users = new LinkedList<User>();
		owner.getRoleList().add(new Role(this, "Creator"));
		users.add(owner);
		this.name = name;
		
		
		this.status = status;
		this.taggedIdeas = taggedIdeas;
	//	taggedIdeas.add(newlyTaggedIdea);
		//this.tagNames = tagNames;
		

	}

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	/**
	 * constructor for a tagging an organization
	 *
	 * @author     nora zakhary
	 * @version    2011.04.29
	 * @param     User owner, String name, LinkedList<User> followers,
			String status, LinkedList<Organization> taggedOrganizations,
			LinkedList<String> tagNames   
	 */
	public Tag(User owner, String name, LinkedList<User> followers,
			String status, LinkedList<Organization> taggedOrganizations
			/*LinkedList<String> tagNames*/) {
		
		users = new LinkedList<User>();
		owner.getRoleList().add(new Role(this, "Creator"));
		users.add(owner);
		this.name = name;
	
		this.status = status;
		this.taggedOrganizations = taggedOrganizations;
		//this.tagNames = tagNames;

	}

	/**
	 * constructor for a tagging an Entity
	 *
	 * @author     nora zakhary
	 * @version    2011.04.29
	 * @param     User owner, String name, LinkedList<User> followers,
			LinkedList<models.Entity> taggedEntity, String status,
			LinkedList<String> tagNames   
	 */
	public Tag(User owner, String name, LinkedList<User> followers,
			LinkedList<Eentity> taggedEntity, String status,
			LinkedList<String> tagNames) {
		users = new LinkedList<User>();
		owner.getRoleList().add(new Role(this, "Creator"));
		users.add(owner);
		this.name = name;
	
		this.status = status;
		this.taggedEntity = taggedEntity;
		//this.tagNames = tagNames;

	}

	/**
	 * constructor for a tagging an Entity
	 *
	 * @author     nora zakhary
	 * @version    2011.04.29
	 * @param    User owner, String name, LinkedList<User> followers,
			LinkedList<Topic> taggedTopic, LinkedList<String> tagNames,
			String status   
	 */
	public Tag(User owner, String name, LinkedList<User> followers,
			LinkedList<Topic> taggedTopic, LinkedList<String> tagNames,
			String status) {
		users = new LinkedList<User>();
		owner.getRoleList().add(new Role(this, "Creator"));
		users.add(owner);
		this.name = name;
		
		this.status = status;
		this.taggedTopics = taggedTopic;
		//this.tagNames = tagNames;

	}

	public User getOwner() {
		for (int i=0;i<users.size();i++)
		{
			for(int j = 0; j< users.get(i).getRoleList().size(); j++) {
				if (users.get(i).getRoleList().get(j).getTitle().equalsIgnoreCase("Creator") &&
						(users.get(i).getRoleList().get(j).getRelatedTag() != null)
					&&	users.get(i).getRoleList().get(j).getRelatedTag().equals(this)) {
				return users.get(i);
				}
			}
			
		}
		return null;
	}
	
	
	
	
	/**
	 * Returns if A tagName is Found in the System or Not
	 *  
	 * @author   Ibrahim Kessba
	 * @version  2010.0428
	 * @category C2S12
	 * @return   Boolean ? True Name is Found , False ,Not found
	 *           Method will also be used in the Equivlant Tags Controller
***/

public static boolean isTagFound(String name) {

	/*long ownerUserId*///Will be used in the Testing cases
	
	//Checking that the tag name is not found
		if (find("byName", name).first() == null )
			return false;
		return true;
	}


	public void setOwner (User owner){
		Role role = new Role (this,"Creator").save();
		role.save();
		owner.getRoleList().add(role);
		owner.addTag(this);
		users.add(owner);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	

	public LinkedList<User> getFollowers() {
		LinkedList<User> followers  = new LinkedList<User>();
		
		
		for (int i=0;i<users.size();i++)
		{
			for(int j = 0; j< users.get(i).getRoleList().size(); j++) {
				if (users.get(i).getRoleList().get(j).getTitle().equalsIgnoreCase("Follower") &&
						(users.get(i).getRoleList().get(j).getRelatedTag() != null)
					&&	users.get(i).getRoleList().get(j).getRelatedTag().equals(this)) {
					followers.add(users.get(i));
				}
			}
			
		}
		return followers;
	}

	public void setFollowers(User follower) {
		follower.getRoleList().add(new Role(this,"Follower"));
		users.add(follower);
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public LinkedList<Organization> getTaggedOrganizations() {
		return (LinkedList<Organization>) taggedOrganizations;
	}

	public void setTaggedOrganizations(
			LinkedList<Organization> taggedOrganizations) {
		this.taggedOrganizations = taggedOrganizations;
	}

	
	public List<Idea> getTaggedIdeas() {
		return taggedIdeas;
	}

	public void setTaggedIdeas(List<Idea> taggedIdeas) {
		this.taggedIdeas = taggedIdeas;
	}

	public LinkedList<Eentity> getTaggedEntity() {
		return (LinkedList<Eentity>) taggedEntity;
	}

	public void setTaggedEntity(LinkedList<Eentity> taggedEntity) {
		this.taggedEntity = taggedEntity;
	}


	public LinkedList<Topic> getTaggedTopics() {
		return (LinkedList<Topic>) taggedTopics;
	}

	public void setTaggedTopics(LinkedList<Topic> taggedTopics) {
		this.taggedTopics = taggedTopics;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public Role getRole() {
		return role;
	}

	public void setItems(List<Item> items) {
		this.items = items;
	}

	public List<Item> getItems() {
		return items;
	}
	
	public void addFollowers(User user) {
		
		if(users.contains(user)){
			users.add(user);
			user.addTag(this);
		}
	}

	public void addTopic(Topic topic) {
		
		if(!taggedTopics.contains(topic)){
			taggedTopics.add(topic);
			topic.addTag(this);
		}
	}

	public void addItem(Item item) {
		// TODO Auto-generated method stub
		if (!items.contains(item)) {
			items.add(item);
			item.addTag(this);
		}
	}

	public void addOrganization(Organization org) {
		if(!taggedOrganizations.contains(org)) {
			taggedOrganizations.add(org);
			org.addTag(this);
		}
	}

	public void addIdea(Idea idea) {
		if(!taggedIdeas.contains(idea)) {
			taggedIdeas.add(idea);
			idea.addTag(this);
		}
	}

	public void addEntity(Eentity entity) {
		if(!taggedEntity.contains(entity)) {
			taggedEntity.add(entity);
			entity.addTag(this);
		}
	}

	

}